package product;


import enums.GoodsStatus;
import enums.ProductStatus;
import enums.ReviewStatus;
import goods.Goods;
import helper.CacheCallBack;
import helper.CacheHelper;
import jodd.bean.BeanCopy;
import models.BaseModel;
import models.constants.DeletedStatus;
import models.merchant.Merchant;
import models.merchant.enums.VerifyState;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import play.modules.paginate.JPAExtPaginator;
import product.enums.ProductAttribute;
import product.merchant.ProductSpecMerchant;
import product.type.AdminProductType;
import product.type.ProductType;
import util.common.ConvertUtil;

import javax.persistence.*;
import java.util.*;

/**
 * 产品基本信息
 * 产品添加时
 * 1. 需要调用 AliyunOpenSearch.uploadProduct 方法 . 将 product 信息 保存到 Aliyun OpenSearch 中
 * 2. 需要调用 CacheHelper.productAddToCache 方法. 将 product 信息 保存到 Cache中.
 * Created by upshan on 15/7/7.
 */
@Entity
@Table(name = "products")
public class Product extends BaseModel {

    public static final String CACHE_PRODUCT_LIST = "ULC_CACHE_PORDUCT_LIST";
    public static final String CACHE_PRODUCT_ID = "ULC_CACHE_PRODUCT_";
    public static final String REDIS_LOCK_KEY = "LocalCouponLock";


    /**
     * 商户信息
     */
    @JoinColumn(name = "merchant_id")
    @ManyToOne
    public Merchant merchant;


    /**
     * * 规格
     */
    @Column(name = "spec")
    public String spec;

    /**
     * 单位
     */
    @Column(name = "unit")
    public String unit;

    /**
     * 产品编号
     */
    @Column(name = "code")
    public String code;

    // ----------------------------------------------------------------------
    /**
     * 名称
     */
    @Column(name = "name")
    public String name;

    /**
     * 简称
     */
    @Column(name = "short_name")
    public String shortName;

    /**
     * 所属类别
     */
    @JoinColumn(name = "product_type_id")
    @ManyToOne
    public ProductType productType;



    /**
     * 所属类别父类
     */
    @JoinColumn(name = "parent_type_id")
    @ManyToOne
    public ProductType parentType;

    /**
     * 主图 在切换型号的时候展示
     */
    @Column(name = "main_image")
    public String mainImage;

    /**
     * 商户自定义价格
     */
    @Column(name = "merchant_price")
    public Double merchantPrice ;

    /**
     * 库存数量
     */
    @Column(name = "stock")
    public Double stock;

    /**
     * Pc产品详情展示
     */
    @Lob
    @Column(name = "pc_content")
    public String pcContent;

    /**
     * 商品上下架状态
     */
    @Column(name = "product_status")
    @Enumerated(EnumType.STRING)
    public ProductStatus productStatus;


    // ----------------------------------------------------------------------

    /**
     * 产品归属 ,SELF_SUPPORT:自营;AGENT_PRODUCT:入住\代理产品
     */
//    @Enumerated(EnumType.STRING)
//    @Column(name = "product_belong")
//    public ProductBelong productBelong;


    /**
     * 产品类型
     */
    @Enumerated(EnumType.STRING)
    public ProductAttribute type;

    /**
     * 所属分类
     */
    @ManyToOne
    @JoinColumn(name = "admin_product_type_id")
    public AdminProductType adminProductType;


    /**
     * 增加销售数量
     */
    @Column(name = "sales_volumes")
    public Integer salesvolumes = 0;


    /**
     * 市场价格
     */
    @Column(name = "market_price")
    public Double marketPrice ;


    /**
     * 做促销时候 展示原价使用
     */
    @Column(name = "old_price")
    public Double oldPrice ;


    /**
     * 冻结状态
     */
    @Column(name = "review_status")
    @Enumerated(EnumType.STRING)
    public ReviewStatus reviewStatus;


    /**
     * 卖点
     */
    @Column(name = "selling_point")
    public String sellingPoint;

    /**
     * 规格型号
     */
    @Column(name = "standard")
    public String standard;

    /**
     * 产品内容介绍
     */
    @Lob
    @Column(name = "content")
    public String content;

    /**
     * 创建时间
     */
    @Column(name = "created_at")
    public Date createdAt;

    /**
     * 创建时间
     */
    @Transient
    public String createTimeStr;

    /**
     * 逻辑删除,0:未删除，1:已删除
     */
    @Enumerated(EnumType.ORDINAL)
    public DeletedStatus deleted;

    /**
     * 备注
     */
    @Column(name = "remark")
    public String remark;

    /**
     * 访问量
     */
    @Column(name = "visit_count")
    public Integer visitCount;

    /**
     * 权重值
     */
    @Column(name = "weight_value")
    public Integer weightValue = 0;

    /**
     * 构建 Goods
     *
     * @return
     */
    public Goods findOrCreateGoods() {
        Goods goods = Goods.find(" serialId = ?1 and deleted = ?2",this.id, DeletedStatus.UN_DELETED).first();
        Product product = Product.findByProductId(this.id);
        if (goods == null) {
            goods = new Goods();
            goods.createdAt = new Date();
            goods.name = this.name;
            goods.deleted = DeletedStatus.UN_DELETED;
//            goods.type = GoodsType.PRODUCT;
            goods.status = GoodsStatus.OPEN;
            goods.serialId = this.id;
            goods.salePrice = this.merchantPrice;
            goods.img = this.mainImage;
            goods.spec = this.spec;
            goods.unit = this.unit;
            goods.merchant = product.merchant;
            goods.save();
        } else {
            goods.name = this.name;
            goods.deleted = DeletedStatus.UN_DELETED;
            goods.status = GoodsStatus.OPEN;
            goods.serialId = this.id;
            goods.salePrice = this.merchantPrice;
            goods.img = this.mainImage;
            goods.spec = this.spec;
            goods.unit = this.unit;
            goods.merchant = product.merchant;
            goods.save() ;
        }
        return goods;
    }

    public Goods findGoods() {
        Goods goods =  Goods.find(" serialId = ?1 and deleted = ?2 ", this.id, DeletedStatus.UN_DELETED ).first();
        if(goods == null){
            goods = findOrCreateGoods();
        }
        return goods;
    }





    /**
     * 分页查询.
     */
    public static JPAExtPaginator<Product> findByCondition(Map<String, Object> conditionMap, String orderByExpress, int pageNumber, int pageSize) {
        StringBuilder xsqlBuilder = new StringBuilder("t.deleted=models.constants.DeletedStatus.UN_DELETED and t.reviewStatus = 'NORMAL' ")
                .append("/~ and t.name like {name} ~/")
                .append("/~ and t.shortName like {shortName} ~/")
                .append("/~ and t.productStatus = {productStatus} ~/")
                .append("/~ and t.merchant.verifyState = {verifyState} ~/")
                .append("/~ and t.parentType.id = {parentType} ~/")
                .append("/~ and t.productType.id = {productType} ~/")
                .append("/~ and t.merchant.name like {merchantName} ~/")
                .append("/~ and t.reviewStatus = {reviewStatus} ~/")
                .append("/~ and t.shortName like {shortName} ~/");


        //if(conditionMap.get("payedOrder")!=null)xsqlBuilder.append(" and (t.status ="+OrderStatus.PAID+" or t.status="+OrderStatus.DISTRIBUTION+") ");

        /**
         *    Query query = t.id = {id};
         *    query.setPropery("id" , conditionMap.get("id"));
         */
        util.xsql.XsqlBuilder.XsqlFilterResult result = new util.xsql.XsqlBuilder().generateHql(xsqlBuilder.toString(), conditionMap);
        JPAExtPaginator<Product> orderPage = new JPAExtPaginator<Product>("Product t", "t", Product.class,
                result.getXsql(), conditionMap).orderBy(orderByExpress);
        orderPage.setPageNumber(pageNumber);
        orderPage.setPageSize(pageSize);
        orderPage.setBoundaryControlsEnabled(false);
        return orderPage;
    }

    /**
     * Update
     *
     * @param id
     * @param newObject
     */
    public static void update(Long id, Product newObject) {
        Product product = Product.findById(id);
        BeanCopy.beans(newObject, product).ignoreNulls(true).copy();
        product.save();
    }

    /**
     * 根据层级查找产品类型
     *
     * @return
     */
    public static List<Product> findAllProducts(final long id, long merchantId) {
        return Product.find("deleted = ?1 and productType.id = ?2 and productStatus = ?3 and merchant.id = ?4 order by created_at desc", DeletedStatus.UN_DELETED, id, ProductStatus.UP, merchantId).fetch();
    }

    /**
     * 根据层级查找产品类型
     *
     * @return
     */
    public static List<Product> findAllProducts(long merchantId) {
        return Product.find("deleted = ?1  and merchant.id = ?2 and reviewStatus = ?3  order by created_at desc", DeletedStatus.UN_DELETED,  merchantId,ReviewStatus.NORMAL).fetch();
    }

    public static Product findByIdFromCache(final Long id) {
        return CacheHelper.getCache(CacheHelper.CACHE_PRODUCT + id, new CacheCallBack<Product>() {
            @Override
            public Product loadData() {
                Product product = Product.find("id = ?1", id).first();
                return product;
            }
        });
    }

    @Transient
    public String getRedisLockKey() {
        return Product.REDIS_LOCK_KEY + this.id + "@product";
    }

    //生成产品编号
    public static String createCode(AdminProductType adminProductType) {
        long number = Product.count("adminProductType.id=?1", adminProductType.id) + 1;
        return number >= 10000 ? ConvertUtil.toString(adminProductType.code) + number : ConvertUtil.toString(adminProductType.code) + ConvertUtil.toString(10000 + number).substring(1);
    }

    /**
     * 根据id查询产品
     */
    public static Product findByProductId(long id) {
        return Product.find("id=?1 and deleted=?2", id, DeletedStatus.UN_DELETED).first();
    }

    /**
     * 获取商品在同一商户下不同的规格,返回字符串
     *
     * @param specMerchant
     * @return
     */
    public static String SetStandard(ProductSpecMerchant specMerchant) {
        String standard = "";
        long merchantId = ConvertUtil.toLong(specMerchant.merchant.id);
        long productId = ConvertUtil.toLong(specMerchant.productSpec.product.id);
        List<ProductSpecMerchant> specMerchantList = ProductSpecMerchant.find(" productSpec.product.id = ?1 and merchant.id = ?2 and deleted = 0", productId, merchantId).fetch();
        for (ProductSpecMerchant productSpecMerchant : specMerchantList) {
            standard += "/" + ConvertUtil.toString(productSpecMerchant.productSpec.spec);
        }
        return standard;

    }

    /**
     * 获取某类别下的产品
     * @param typeId
     * @return
     */
    public static List<Product> loadByTypeAndMerchant(long typeId , long merchantId){
        List<Product> productList = Product.find(" deleted = ?1 and productType.id = ?2 and merchant.id = ?3 and productStatus = ?4 and reviewStatus = ?5" , DeletedStatus.UN_DELETED , typeId , merchantId , ProductStatus.UP,ReviewStatus.NORMAL).fetch();
        return productList;
    }

    //判断产品库存是否足够减去购买数量
    public static Boolean checkStock(Product product , Integer buyNum){
        if(product.stock - buyNum >= 0)
            return true;
        else
            return false ;

    }

    /**
     *  首页商品分类
     * @param typeId
     * @return
     */
    public static List<Product> getProductListByType(long  typeId,int pageNum) {
        String sqlSelect  = "select p.id as id ,p.name as name , p.main_image as mainImage,p.merchant_price merchantPrice ,p.old_price oldPrice,p.spec spec,p.unit unit  from products p left join power_merchants pm  on p.merchant_id = pm.id " +
                "   where p.product_status ='UP' and  p.review_status = 'NORMAL'  and p.deleted = 0 and pm.deleted = 0 and pm.verify_state = 'PASS' " +
                " and ( p.product_type_id ="+typeId+
                " or p.parent_type_id ="+typeId+
                ")    LIMIT " + pageNum + ", 10";
        Query query = em().createNativeQuery(sqlSelect);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Product> resulList = query.getResultList();
        return  resulList;
    }

    /**
     * 根据名字查询产品
     */
    public static List<Product> findByProductName(String name) {
        return Product.find("name =?1 and deleted=?2 and reviewStatus = ?3", name, DeletedStatus.UN_DELETED,ReviewStatus.NORMAL).fetch();
    }

    /**
     * 商户端 查询商品,商品已审核通过
     * @param merchantId
     * @param typeId
     * @return
     */
    public static List<Product> loadByMerchantIdAndType(long merchantId , long typeId){
        return Product.find("  deleted = ? and productType.id = ? and merchant.id = ? and productStatus = ? and  reviewStatus = ?" , DeletedStatus.UN_DELETED , typeId , merchantId , ProductStatus.UP ,  ReviewStatus.NORMAL).fetch();
    }


    /**
     * 获取产品分类,并获取分类下的产品
     * @param merchantId
     * @return
     */
    public static List<Map<String,Object>> getProductsByType(long merchantId){
        List<Map<String,Object>> productList = new ArrayList<>();

        List<ProductType> productTypeList = ProductType.loadAll();
        if(productTypeList != null && productTypeList.size() > 0){
            for(ProductType productType : productTypeList){
                Map<String , Object> typeMap = new HashMap<>();
                List<Product> products = Product.loadByMerchantIdAndType(merchantId , productType.id);
                if(products != null && products.size() > 0){
                    typeMap.put("type" , productType);
                    typeMap.put("productList" , products);
                    productList.add(typeMap);

                }
            }
        }

        return productList ;
    }
    /**
     *  首页商品分类
     * @param typeId
     * @return
     */
    public static List<Product> getProductListByTypeAndMerchant(long  typeId,int pageNum,long merchantId) {
        String sqlSelect  = "select p.id as id ,p.name as name , p.main_image as mainImage,p.merchant_price merchantPrice ,p.old_price oldPrice,p.spec spec,p.unit unit,p.visit_count visitCount  " +
                "   from products p left join power_merchants pm  on p.merchant_id = pm.id" +
                "   where p.product_status ='UP' and  p.review_status = 'NORMAL'  and p.deleted = 0 and pm.deleted = 0 and pm.verify_state = 'PASS' " +
                " and ( p.product_type_id ="+typeId+
                " or p.parent_type_id ="+typeId+
                ")  and p.merchant_id ="+merchantId +
                "   LIMIT " + pageNum + ", 10";

        Query query = em().createNativeQuery(sqlSelect);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Product> resulList = query.getResultList();
        return  resulList;
    }

    /**
     * 获取产品分类,并获取分类下的产品
     *
     * @return
     */
    public static List<ProductType> getProductListByType(){
        List<ProductType> firstTypeList = ProductType.loadAllParentType(0);
        return firstTypeList ;
    }
    /**
     *  首页商品分类
     * @param typeId
     * @return
     */
    public static List<Product> getProductListByTypeAndMerchant(long  typeId,long merchantId) {
        String sqlSelect  = "select p.id as id ,p.name as name , p.main_image as mainImage,p.merchant_price merchantPrice ,p.old_price oldPrice,p.spec spec,p.unit unit,p.visit_count visitCount  " +
                "  from products p " +
                "   where p.product_status ='UP' and  p.review_status = 'NORMAL'  and p.deleted = 0 " +
                " and ( p.product_type_id ="+typeId+
                " or p.parent_type_id ="+typeId+
                ")  and p.merchant_id ="+merchantId ;
        Query query = em().createNativeQuery(sqlSelect);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Product> resulList = query.getResultList();
        return  resulList;
    }

    /**
     * 根据id查询产品
     */
    public static Product findById(long id) {
        return Product.find("id=?1 ", id).first();
    }

    /**
     * 所有可用商品
     * @return
     */
    public static List<Product> getProductListByStatus(){
        return  Product.find(" deleted = ?1  and productStatus = ?2 ",DeletedStatus.UN_DELETED,ProductStatus.UP).fetch();
    }

    /**
     * 商户的所有产品
     * @param merId 商户ID
     * @return
     */
    public static List<Product> getProductListByMerId(long merId){
        return  Product.find(" deleted = ?1  and productStatus = ?2 and  reviewStatus = ?3 and merchant.id = ?4  ",DeletedStatus.UN_DELETED,ProductStatus.UP,ReviewStatus.NORMAL,merId).fetch();
    }


    /**
     * 所有可用商品
     * @return
     */
    public static List<Product> getProductListByStatusAndDay(Date beginDate, Date endDate){
        return  Product.find(" deleted = ?1  and productStatus = ?2 and createdAt between ?3 and ?4 ",DeletedStatus.UN_DELETED,ProductStatus.UP,beginDate,endDate ).fetch();
    }


    /**
     * 商户的所有产品
     * @return
     */
    public static List<Product> getAllProductList(){
        return  Product.find(" deleted = ?1  and productStatus = ?2 and  reviewStatus = ?3  ",DeletedStatus.UN_DELETED,ProductStatus.UP,ReviewStatus.NORMAL).fetch();
    }

    /**
     * 小类相关产品
     * @param typeId
     * @return
     */
    public static List<Product> loadByProType(long typeId){
        return Product.find("  deleted = ?1 and productType.id = ?2 and productStatus = ?3 and  reviewStatus = ?4" , DeletedStatus.UN_DELETED , typeId ,ProductStatus.UP ,  ReviewStatus.NORMAL).fetch();
    }

    public static List<Product> findAllProductsByNameAndMerchantPrice(String proName,String orderWord,String orderBy) {
        if(orderBy.equals("-")){
            return Product.find("deleted = ?1  and merchant.verifyState = ?2 and reviewStatus = ?3  and name like ?4  and productStatus = ?5 order by merchantPrice desc", DeletedStatus.UN_DELETED, VerifyState.PASS,ReviewStatus.NORMAL,"%" + proName + "%",ProductStatus.UP).fetch();
        }else{
            return Product.find("deleted = ?1  and merchant.verifyState = ?2 and reviewStatus = ?3   and name like ?4  and productStatus = ?5 order by merchantPrice asc", DeletedStatus.UN_DELETED, VerifyState.PASS,ReviewStatus.NORMAL,"%" + proName + "%",ProductStatus.UP).fetch();
        }

    }

    public static List<Product> findAllProductsByNameAndSalesvolumes(String proName,String orderWord,String orderBy) {
        if(orderBy.equals("-")){
            return Product.find("deleted = ?1  and merchant.verifyState = ?2 and reviewStatus = ?3  and name like ?4  and productStatus = ?5 order by salesvolumes desc", DeletedStatus.UN_DELETED, VerifyState.PASS,ReviewStatus.NORMAL,"%" + proName + "%",ProductStatus.UP).fetch();
        }else{
            return Product.find("deleted = ?1  and merchant.verifyState = ?2 and reviewStatus = ?3   and name like ?4  and productStatus = ?5 order by salesvolumes asc", DeletedStatus.UN_DELETED, VerifyState.PASS,ReviewStatus.NORMAL,"%" + proName + "%",ProductStatus.UP).fetch();
        }

    }

    public static List<Product> findAllProductsByNameNoOrder(String proName) {
         return Product.find("deleted = ?1  and merchant.verifyState = ?2 and reviewStatus = ?3   and name like ?4  and productStatus = ?5 order by weightValue desc", DeletedStatus.UN_DELETED, VerifyState.PASS,ReviewStatus.NORMAL,"%" + proName + "%",ProductStatus.UP).fetch();

    }
}
